package com.coolw.core.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

/**
 * 枚举基类
 *
 * @author coolw
 * @date 2023/11/11 13:51
 */
public interface BaseEnum<T> {

    /**
     * 将code，msg放到容器中缓存;枚举类继承BaseEnum,在构造方法中调用此方法完成数据初始化
     */
    default void initEnum(T code, String msg) {
        EnumContainer.putEnum(this, code, msg);
    }

    default T getCode() {
        return EnumContainer.getEnum(this).getCode();
    }

    default String getMsg() {
        return EnumContainer.getEnum(this).getMsg();
    }

    static <T> void clear(Class<? extends BaseEnum<T>> clazz) {
        EnumContainer.clear(clazz);
    }

    static void clearAll() {
        EnumContainer.clearAll();
    }

    /**
     * 根据code获取枚举
     */
    static <T, R extends BaseEnum<T>> R getEnumBycode(Class<? extends BaseEnum<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter(enumBean -> enumBean.getCode().equals(code))
                .map(v -> (R) v)
                .findAny()
                .orElse(null);
    }

    /**
     * 检查code是否在枚举类定义中
     */
    static <T> boolean checkIsExist(Class<? extends BaseEnum<T>> clazz, T code) {
        return getEnumBycode(clazz, code) != null;
    }

    /**
     * 枚举容器，用于存储枚举值
     */
    class EnumContainer {

        private static final Map<BaseEnum, EnumParam> ENUM_MAP = new ConcurrentHashMap<>();

        public static <T> void putEnum(BaseEnum<T> baseEnum, T code, String msg) {
            ENUM_MAP.put(baseEnum, new EnumParam(code, msg));
        }

        public static <K extends BaseEnum<T>, T> EnumParam<T> getEnum(K baseEnum) {
            return ENUM_MAP.get(baseEnum);
        }

        public static <T> void clear(Class<? extends BaseEnum<T>> clazz) {
            Stream.of(clazz.getEnumConstants()).forEach(ENUM_MAP::remove);
        }

        public static void clearAll() {
            ENUM_MAP.clear();
        }
    }

    /**
     * 枚举类属性定义
     */
    @Getter
    @AllArgsConstructor
    class EnumParam<T> {

        private final T code;

        private final String msg;
    }
}
